using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;
using WCFDicing.ServiceContracts;
using WCFDicing.BusinessLogic;
using WCFDicing.DataContracts;
using WCFDicing.BusinessEntities;

namespace WCFDicing.ServiceImplementation
{
    /// <summary>
    /// serwer zarzadzajacy stolami na ktorych odbywaja sie gry w kosci
    /// </summary>
    [ServiceBehavior( Name = "DicingGame", Namespace = "http://WCFDicing.ServiceContracts/2008/01" )]
    public class DicingGameService : IDicingGame
    {
        /// <summary>
        /// lista gier
        /// </summary>
        static Dictionary<int, DicingGame> RoomList = new Dictionary<int, DicingGame>();

        /// <summary>
        /// lista stolow
        /// </summary>
        static Dictionary<int, DicingRoom> BasicRoomList = new Dictionary<int, DicingRoom>();

        /// <summary>
        /// zliczania ilosci stolow
        /// </summary>
        static int Index;

        /// <summary>
        /// connection-string do bazy danych
        /// </summary>
        static string DataBasePath="CasinoDB";

        /// <summary>
        /// obiekt obslugujacy polaczenia z baza danych
        /// </summary>
        CasinoUsersManager UserManager = new CasinoUsersManager(DataBasePath);

        /// <summary>
        /// sprawdzanie czy istnieje stol o podanym id
        /// </summary>
        /// <param name="ID">id stolu</param>
        /// <returns>czy istnieje stol o podanym id</returns>
        private bool CheckRoom(int ID)
        {
            return RoomList.ContainsKey(ID);
        }


        #region IDicingGame Members

        /// <summary>
        /// obsluga dolanczania nowego gracza do gry
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public JoinResponse Join( JoinRequest request )
        {

            JoinResponse response = new JoinResponse( );
            response.check = false;
            if ( CheckRoom( request.GameID ) )
            {
                //pobieramy kase z bazy
                //request.player.MoneyField = UserManager.GetUserMoney( request.player.PlayerId ).User_Money; 
                if ( RoomList[request.GameID].Join( request.player ) )
                {

                    BasicRoomList[request.GameID].Players++;
                    response.check = true;
                }
            }
            return response;
        }

        /// <summary>
        /// obsluga zlozenia zakladu przez gracza
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public BetResponse Bet( BetRequest request )
        {
            BetResponse response = new BetResponse();
            if (!CheckRoom(request.GameID)) 
                response.check = false;
            else if (RoomList[request.GameID].IsPlaying(request.ID))
                response.check=RoomList[request.GameID].Bet(request.bet, request.ID);
            return response;
        }

        /// <summary>
        /// funkcja zwracajaca aktualny stan stolu z gry
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public TableResponse GetTable( TableRequest request )
        {
            TableResponse resp = new TableResponse( );

            if ( CheckRoom( request.GameID ) )
                if ( RoomList[request.GameID].IsPlaying( request.PlayerID ) || request.PlayerID == 0 )
                {
                    resp.table = RoomList[request.GameID].GetTable( request.PlayerID );
                }

            return resp;
        }

        /// <summary>
        /// funkcja rozpoczynajaca runde
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public BeginResponse Begin( BeginRequest request )
        {
            BeginResponse response = new BeginResponse( );
            response.result = false;
            if ( CheckRoom( request.GameID ) )
                if ( RoomList[request.GameID].IsPlaying( request.PlayerID ) )
                    if ( RoomList[request.GameID].Table.PlayerThrowId == request.PlayerID && RoomList[request.GameID].Table.TableAction == DicingActionList.NewRound )
                        response.result = RoomList[request.GameID].Begin( );
                    else if( RoomList[request.GameID].Table.PlayerOwnerId == request.PlayerID && RoomList[request.GameID].Table.TableAction == DicingActionList.FirstRound)
                        response.result = RoomList[request.GameID].Begin( );
            return response;
        }

        /// <summary>
        /// fukcja tworzy nowy pokoj do gry
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public CreateRoomResponse CreateRoom( CreateRoomRequest request )
        {
            Index++;
            RoomList.Add(Index, new DicingGame(request.Settings, request.RoomName));
            DicingRoom room = new DicingRoom();
            room.Name = request.RoomName;
            room.ID = Index;
            room.Options = request.Settings;
            BasicRoomList.Add(Index,room);
            
            return new CreateRoomResponse(Index);
        }

        /// <summary>
        /// funkcja obsluguje opuszczenie pokoju przez gracza
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public LeaveRoomResponse LeaveRoom( LeaveRoomRequest request )
        {
            LeaveRoomResponse response = new LeaveRoomResponse( false );
            //response.check = false;
            if ( CheckRoom( request.GameID ) )
                if ( RoomList[request.GameID].IsPlaying( request.PlayerID ) )
                {
                    //pobieramy kase jaka aktualnie ma gracz na stole
                    int money = RoomList[request.GameID].Table.Players[request.PlayerID].MoneyField;
                    response.check = RoomList[request.GameID].EndGame( request.PlayerID );

                    if ( response.check )
                    {
                        //jesli wyjscie sie udalo aktualizujemy kase na koncie
                        //UserManager.UpdateUserMoney(new CASINO_USER_MONEY(request.PlayerID, money));
                        BasicRoomList[request.GameID].Players--;
                        if ( RoomList[request.GameID].Table.Players.Count == 0 )
                        {
                            RoomList.Remove( request.GameID );
                            BasicRoomList.Remove( request.GameID );
                        }
                    }
                }
            return response;
        }

        /// <summary>
        /// funkcja zwraca aktualnie grajacego ze stolu
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public ActualPlayerResponse ActualPlayer( ActualPlayerRequest request )
        {
            ActualPlayerResponse resp = new ActualPlayerResponse( );
            resp.ID = 0;

            if ( CheckRoom( request.GameID ) )

                resp.ID = RoomList[request.GameID].Table.PlayerBidId;
            return resp;
        }

        /// <summary>
        /// funkcja pobiera liste stolow z serwera
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public GetRoomListResponse GetRoomList( GetRoomListRequest request )
        {
            GetRoomListResponse resp = new GetRoomListResponse( );
            resp.DicingRoomList = new List<DicingRoom>( BasicRoomList.Values );

            //aktualizujemy akcje dla pokoi
            foreach ( DicingRoom room in resp.DicingRoomList )
            {
                room.Action = RoomList[room.ID].Table.TableAction;
            }

            return resp;
        }

        /// <summary>
        /// funkcja rozpoczyna symulacje rzutu na serwerze
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public SimulationResponse StartSimulation( SimulationRequest request )
        {
            SimulationResponse response = new SimulationResponse( );
            DicingResult result = new DicingResult();
            if ( !CheckRoom( request.GameID ) )
                return response;
            else if ( RoomList[request.GameID].IsPlaying( request.ID ) && RoomList[request.GameID].Table.PlayerThrowId == request.ID )
                result = RoomList[request.GameID].NextThrow( request.ID, request.Animation );

            response.Result = result;
            return response;
        }

        #endregion
    }
}
